﻿using System;
using log4net;
using Reactor.Environment;
using Reactor.ServiceGrid;

namespace Reactor.Messaging
{
    public abstract class MessageHandlerBase<T> : IMessageHandler<T> where T : class
    {
        protected static ILog Log;

        /// <summary>
        /// Initializes a new instance of the <see cref="MessageHandlerBase&lt;T&gt;"/> class.
        /// </summary>
        protected MessageHandlerBase()
        {
            Log = LogManager.GetLogger(GetType());
        }

        #region Implementation of IMessageHandler<T>

        /// <summary>
        /// Handles the message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="messageContext">Context provided with message deliver</param>
        public void Handle(T message, IMessageContext messageContext)
        {
            if(Log.IsDebugEnabled) Log.DebugFormat("Handling message of type: {0}", typeof(T));

            OnHandling(message, messageContext);
        }

        #endregion

        public abstract void OnHandling(T message, IMessageContext messageContext);

        protected IReactorCore GetCurrentServiceAsReactorCore()
        {
            AssertThatCurrentServiceIsAReactorCore();

            return (IReactorCore) Context.GridContext.CurrentReactorService;
        }

        protected void AssertThatCurrentServiceIsAReactorService()
        {
            AssertThatCurrentServiceExistsOnGridContext();

            if(typeof(IReactorCore).IsAssignableFrom(Environment.Context.GridContext.CurrentReactorService.GetType()))
                throw new InvalidOperationException("Current service found in grid context is not a managed Reactor Service. Rather, it is a Reactor Core.");
        }

        protected void AssertThatCurrentServiceIsAReactorCore()
        {
            AssertThatCurrentServiceExistsOnGridContext();

            if (!typeof(IReactorCore).IsAssignableFrom(Environment.Context.GridContext.CurrentReactorService.GetType()))
                throw new InvalidOperationException("Current service found in grid context is not a Reactor Core.");
        }

        protected void AssertThatCurrentServiceExistsOnGridContext()
        {
            if (Environment.Context.GridContext.CurrentReactorService == null)
                throw new InvalidOperationException("No current service found on grid context.");
        }
    }
}
